﻿using System.Xml;

namespace Toybox.NicoSharp.Video
{
	using Extensions;

	public class PacketCreatorV2009 : PacketCreatorV2006
	{

		#region [Static]

		public new const string VERSION = "20090904";

		#endregion [Static]


		#region Constructor

		public PacketCreatorV2009(Flv flv)
			: base(flv)
		{
			this.LeafResFrom = 100;
		}

		#endregion Constructor


		#region Public Members

		public int LeafResFrom
		{
			get;
			set;
		}

		public int ResBefore
		{
			get { return this.Thread == null ? 0 : this.Thread.last_res + 1; }
		}

		#endregion Public Members


		#region Protected Methods

		protected virtual string GetLeafResFrom()
		{
			string result = "0-" + ((this.Flv.l + 10) / 60 + 1);
			result += ":" + (100 < this.LeafResFrom ? 100 : this.LeafResFrom);
			result += "," + this.CoerceResFrom(this.ResFrom);

			return result;
		}


		protected override void AppendUserNode(ref XmlDocument doc)
		{
			XmlNode root = doc.FirstChild;

			string thread = this.Flv.GeneralThreadId;

			if (this.When == null)
			{
				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, null, 0,
					this.Flv.user_id, false, 0, null, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), null, 0,
					this.Flv.user_id, null, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
			else
			{
				WaybackKey waybackKey = new WaybackKey(thread, Flv.Cookies);
				waybackKey.Update();

				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, false, this.ClickRevision, null, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, null, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
		}

		protected override void AppendCommunityNode(ref XmlDocument doc)
		{
			XmlNode root = doc.FirstChild;

			if (this.CommunityThreadKey == null)
				this.CommunityThreadKey = new ThreadKey(this.Flv.CommunityThreadId, this.Flv.Cookies);

			if (this.CommunityThreadKey.Expired)
				this.CommunityThreadKey.Update();

			string thread = this.Flv.CommunityThreadId;

			if (this.When == null)
			{
				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, null, 0,
					this.Flv.user_id, false, 0, this.CommunityThreadKey, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), null, 0,
					this.Flv.user_id, this.CommunityThreadKey, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
			else
			{
				WaybackKey waybackKey = new WaybackKey(thread, Flv.Cookies);
				waybackKey.Update();

				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, false, this.ClickRevision, this.CommunityThreadKey, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, this.CommunityThreadKey, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
		}

		protected override void AppendScriptNode(ref XmlDocument doc)
		{
			XmlNode root = doc.FirstChild;

			string thread = this.Flv.ScriptThreadId;

			if (this.When == null)
			{
				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, null, 0,
					this.Flv.user_id, false, 0, null, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), null, 0,
					this.Flv.user_id, null, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
			else
			{
				WaybackKey waybackKey = new WaybackKey(thread, Flv.Cookies);
				waybackKey.Update();

				XmlElement node = this.CreateThreadNode(doc,
					thread, VERSION, 0, waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, false, this.ClickRevision, null, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);

				node = this.CreateThreadLeavesNode(doc,
					thread, this.GetLeafResFrom(), waybackKey, this.When.Value.GetUnixTime(),
					this.Flv.user_id, null, this.ResBefore, this.Scores, this.Nicoru, this.LanguageId);

				root.AppendChild(node);
			}
		}

		protected virtual XmlElement CreateThreadLeavesNode(XmlDocument doc,
			string thread, string res,
			WaybackKey waybackKey, int when,
			string user_id,
			ThreadKey threadKey, int resBefore,
			bool isScores, bool isNicoru, int languageId)
		{
			XmlElement node = doc.CreateElement("thread_leaves");
			node.SetAttribute("thread", thread);

			if (when != 0)
			{
				node.SetAttribute("waybackkey", waybackKey.Value);
				node.SetAttribute("when", when.ToString());
			}

			if (!string.IsNullOrEmpty(user_id))
			{
				node.SetAttribute("user_id", user_id);
			}

			if (threadKey != null)
			{
				node.SetAttribute("threadkey", threadKey.Value);
				if (threadKey.Force184)
				{
					node.SetAttribute("force_184", "1");
				}
			}

			if (resBefore != 0)
			{
				node.SetAttribute("res_before", resBefore.ToString());
			}

			if (isScores)
			{
				node.SetAttribute("scores", "1");
			}

			if (isNicoru)
			{
				node.SetAttribute("nicoru", "1");
			}

			if (languageId != 0)
			{
				node.SetAttribute("nicoru", languageId.ToString());
			}

			node.InnerText = res;

			return node;
		}

		#endregion Protected Methods

	}
}
